import re
from django.shortcuts import render_to_response, get_object_or_404
from django.utils import simplejson as json
from django.http import HttpResponse
from django.template import RequestContext
from django.core.exceptions import FieldError
from pyceab.course.models import Course
# Create your views here.


ALLOWED_FIELDS = [
        'department',
        'course_code',
        'full_name',
        'cse_a',
        'cse_b',
        'cse_c',
        'cse_d',
        'te_math',
        'te_sci',
        'te_engsci',
        'te_engdes',
        'offered_fall',
        'offered_winter',
        'offered_spring',
        ]
ALLOWED_OPERATORS = [
        'gt',
        'lt',
        'gte',
        'lte',
        'contains',
        'icontains',
        'iexact',
        'exact',
        ]

dept_and_course_code = re.compile(r'(?P<department>[a-zA-Z]+)\s*(?P<course_code>[0-9]+[a-zA-Z]{0,1})\s*')

def is_valid_query_param(query):
    parts = query.split('__')
    if parts[0] not in ALLOWED_FIELDS: return False
    return len(parts) == 1 or (len(parts) ==2 and parts[1] in ALLOWED_OPERATORS)



def courses_index(request):
    """
    View to query courses database. Expects
    GET parameters in the request indicating the
    attribute to query on and optional operators.

    Example query string: 
    ?department=SY&department_operator=icontains

    Corresponding DB query:
    Course.objects.filter(department__icontains='SY')

    Any operators that the django query api supports
    are accepted.
    Returns json if called by ajax, renders a template
    otherwise.

    Also supports a 'simple search' feature. This allows
    a simple query parameter to be passed that either represents
    a department and course code or part of the name of a course
    """
    if 'simple_search' in request.GET:
        search_string = request.GET['simple_search']
        match = dept_and_course_code.match(search_string) 
        if match: 
            results = Course.objects.filter(department__icontains=match.group('department'), course_code__icontains=match.group('course_code'))
        else:
            results = Course.objects.filter(full_name__icontains=search_string)
    else:
        query_args = {}
        for param in request.GET:
            query_param = param
            # add operator if present in GET
            if '%s_operator' % param in request.GET:
                query_param += '__%s' % request.GET['%s_operator' % param]
            # check to see if param is valid
            if is_valid_query_param(query_param):
                query_args[query_param.encode('utf8')] = request.GET[param].encode('utf8')

        results = Course.objects.filter(**query_args)
    if request.is_ajax():
        results = json.dumps(results.values())
        return HttpResponse(results)
    else:
        context = {'courses': results}
        return render_to_response('course/index.html',
                context,
                context_instance=RequestContext(request))

def course_detail(request, course_id):
    course = get_object_or_404(Course, id=course_id)
    if request.is_ajax():
        return HttpResponse(json.dumps(dict(course)))
    context =  {'course': course}
    return render_to_response('course/detail.html',
            context,
            context_instance=RequestContext(request))

def autocomplete_data(request):
    courses = Course.objects.filter(core_course=False)
    result = [ {'code': c.short_form, 'name': c.full_name} for c in courses]
    return render_to_response('course/autocomplete_data.js',
        {'ac_data': json.dumps(result)},
        context_instance=RequestContext(request))

